﻿using AJWPFAdmin.Core;
using AJWPFAdmin.Core.Components.AJTable.ViewModels;
using AJWPFAdmin.Core.Components.ViewModels;
using AJWPFAdmin.Core.Components.Views;
using AJWPFAdmin.Core.Enums;
using AJWPFAdmin.Core.ExtensionMethods;
using AJWPFAdmin.Core.Models.EF.Tables;
using AJWPFAdmin.Core.Utils;
using AJWPFAdmin.Core.Validation;
using AJWPFAdmin.Services.AppointAPI;
using AJWPFAdmin.Services.EF;
using Masuit.Tools;
using Masuit.Tools.Systems;
using Microsoft.EntityFrameworkCore;
using Prism.Commands;
using Prism.Events;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Yitter.IdGenerator;
using static AJWPFAdmin.Core.ExceptionTool;

namespace EntranceGuardManager.Modules.Main.ViewModels
{
    public class PassagewayFormViewModel : AnnotationValidationViewModel, IDialogAware
    {
        private string _dialogTitle;
        public string DialogTitle
        {
            get { return _dialogTitle; }
            set { SetProperty(ref _dialogTitle, value); }
        }

        private bool _loading;
        public bool Loading
        {
            get { return _loading; }
            set { SetProperty(ref _loading, value); }
        }

        private Passageway _form;

        private bool _synchronized;
        public bool Synchronized
        {
            get { return _synchronized; }
            set { SetProperty(ref _synchronized, value); }
        }

        private Passageway _selectedPassageway;
        /// <summary>
        /// 当前选中的用于数据填充的道闸
        /// </summary>
        public Passageway SelectedPassageway
        {
            get { return _selectedPassageway; }
            set
            {
                if (SetProperty(ref _selectedPassageway, value))
                {
                    //WatchhouseId = WatchHouseOptions.FirstOrDefault(p => (long)p.Value == value.WatchhouseId);
                    //Name = value.Name;
                    Address = value.Address;
                    Longitude = value.Longitude;
                    Latitude = value.Latitude;
                    ManagerPerson = value.ManagerPerson;
                    ManagerPhone = value.ManagerPhone;
                    ManagerCompany = value.ManagerCompany;
                    CompanyPerson = value.CompanyPerson;
                    CompanyPhone = value.CompanyPhone;
                    WarehouseId = WarehouseOptions.FirstOrDefault(p => (long)p.Value == value.WarehouseId);
                    DeviceGateway = value.DeviceGateway;
                    Remark = value.Remark;
                    CountCarEnable = value.CountCarEnable;
                    Direction = value.Direction;
                }

            }
        }

        private List<Passageway> _passagewayOptions;
        public List<Passageway> PassagewayOptions
        {
            get => _passagewayOptions;
            set => SetProperty(ref _passagewayOptions, value);

        }

        private AJTableFormSchemaItemOptions _watchhouseId;
        [Display(Name = "所属出入口")]
        [Required(ErrorMessage = "{0}必填")]
        public AJTableFormSchemaItemOptions WatchhouseId
        {
            get { return _watchhouseId; }
            set
            {
                SetProperty(ref _watchhouseId, value);
                SaveCmd.RaiseCanExecuteChanged();
            }
        }

        private AJTableFormSchemaItemOptions _warehouseId;
        public AJTableFormSchemaItemOptions WarehouseId
        {
            get { return _warehouseId; }
            set
            {
                SetProperty(ref _warehouseId, value);
                SaveCmd.RaiseCanExecuteChanged();
            }
        }

        private string _name;
        [Display(Name = "名称")]
        [Required(ErrorMessage = "{0}必填")]
        [StringLength(50, ErrorMessage = "{0}超长:{1}")]
        public string Name
        {
            get { return _name; }
            set
            {
                SetProperty(ref _name, value);
                SaveCmd.RaiseCanExecuteChanged();
            }
        }

        private string _code;
        [Display(Name = "编号")]
        [Required(ErrorMessage = "{0}必填")]
        [StringLength(50, ErrorMessage = "{0}超长:{1}")]
        public string Code
        {
            get { return _code; }
            set
            {
                SetProperty(ref _code, value);
                SaveCmd.RaiseCanExecuteChanged();
            }
        }

        private PassagewayDirection _direction;
        public PassagewayDirection Direction
        {
            get { return _direction; }
            set
            {
                SetProperty(ref _direction, value);
            }
        }

        private bool _countCarEnable;
        public bool CountCarEnable
        {
            get { return _countCarEnable; }
            set
            {
                SetProperty(ref _countCarEnable, value);
                SaveCmd.RaiseCanExecuteChanged();
            }
        }

        private string _deviceGateway;
        public string DeviceGateway
        {
            get { return _deviceGateway; }
            set
            {
                SetProperty(ref _deviceGateway, value);
            }
        }

        private string _remark;
        [Display(Name = "备注")]
        [StringLength(100, ErrorMessage = "{0}超长:{1}")]
        public string Remark
        {
            get { return _remark; }
            set
            {
                SetProperty(ref _remark, value);
            }
        }

        private string _address;
        /// <summary>
        /// 地址
        /// </summary>
        [Display(Name = "地址")]
        [Required(ErrorMessage = "{0}必填")]
        [MaxLength(200, ErrorMessage = "{0}超长:{1}")]
        public string Address
        {
            get => _address;
            set { SetProperty(ref _address, value); SaveCmd.RaiseCanExecuteChanged(); }
        }

        private decimal _latitude;
        /// <summary>
        /// 纬度
        /// </summary>
        [Display(Name = "纬度")]
        [Range(0, 90, ErrorMessage = "{0}须在 {1} ~ {2} 度之间")]
        public decimal Latitude
        {
            get => _latitude;
            set { SetProperty(ref _latitude, value); SaveCmd.RaiseCanExecuteChanged(); }
        }

        private decimal _longitude;
        /// <summary>
        /// 经度
        /// </summary>
        [Display(Name = "经度")]
        [Range(0, 180, ErrorMessage = "{0}须在 {1} ~ {2} 度之间")]
        public decimal Longitude
        {
            get => _longitude;
            set { SetProperty(ref _longitude, value); SaveCmd.RaiseCanExecuteChanged(); }
        }

        private string _managerPerson;
        /// <summary>
        /// 负责人
        /// </summary>
        [Display(Name = "负责人")]
        [MaxLength(10, ErrorMessage = "{0}超长:{1}")]
        public string ManagerPerson
        {
            get => _managerPerson;
            set { SetProperty(ref _managerPerson, value); SaveCmd.RaiseCanExecuteChanged(); }
        }

        private string _managerPhone;
        /// <summary>
        /// 负责人联系方式
        /// </summary>
        [Display(Name = "负责人联系方式")]
        [MaxLength(20, ErrorMessage = "{0}超长:{1}")]
        public string ManagerPhone
        {
            get => _managerPhone;
            set { SetProperty(ref _managerPhone, value); SaveCmd.RaiseCanExecuteChanged(); }
        }

        private string _managerCompany;
        /// <summary>
        /// 运维单位名称
        /// </summary>
        [Display(Name = "运维单位名称")]
        [MaxLength(20, ErrorMessage = "{0}超长:{1}")]
        public string ManagerCompany
        {
            get => _managerCompany;
            set { SetProperty(ref _managerCompany, value); SaveCmd.RaiseCanExecuteChanged(); }
        }

        private string _companyPerson;
        /// <summary>
        /// 运维单位名称
        /// </summary>
        [Display(Name = "运维单位联系人")]
        [MaxLength(10, ErrorMessage = "{0}超长:{1}")]
        public string CompanyPerson
        {
            get => _companyPerson;
            set { SetProperty(ref _companyPerson, value); SaveCmd.RaiseCanExecuteChanged(); }
        }

        private string _companyPhone;
        /// <summary>
        /// 运维单位联系方式
        /// </summary>
        [Display(Name = "运维单位联系方式")]
        [MaxLength(20, ErrorMessage = "{0}超长:{1}")]
        public string CompanyPhone
        {
            get => _companyPhone;
            set { SetProperty(ref _companyPhone, value); SaveCmd.RaiseCanExecuteChanged(); }
        }

        private ObservableCollection<AJTableFormSchemaItemOptions> _watchHouseOptions;
        public ObservableCollection<AJTableFormSchemaItemOptions> WatchHouseOptions
        {
            get { return _watchHouseOptions; }
            set
            {
                SetProperty(ref _watchHouseOptions, value);
            }
        }

        private ObservableCollection<AJTableFormSchemaItemOptions> _warehouseOptions;
        public ObservableCollection<AJTableFormSchemaItemOptions> WarehouseOptions
        {
            get { return _warehouseOptions; }
            set
            {
                SetProperty(ref _warehouseOptions, value);
            }
        }

        private Dictionary<string, PassagewayDirection> _directionOptions;
        public Dictionary<string, PassagewayDirection> DirectionOptions
        {
            get { return _directionOptions; }
            set
            {
                SetProperty(ref _directionOptions, value);
            }
        }

        private DelegateCommand _saveCmd;
        public DelegateCommand SaveCmd =>
            _saveCmd ?? (_saveCmd = new DelegateCommand(ExecuteSaveCmdAsync, CanExecuteSaveCmd));

        async void ExecuteSaveCmdAsync()
        {
            if (!ValidateModel())
            {
                SaveCmd.RaiseCanExecuteChanged();

                AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
                {
                    Title = "提示",
                    Message = $"表单校验失败,请检查所填数据",
                    Detail = string.Join(";", ValidationErrorsByProperty.SelectMany(p => p.Value).Select(p => p.ToString()))
                });
                return;
            }

            if (CountCarEnable && WarehouseId == null)
            {
                ExceptionTool.FriendlyError("关联仓库必选", dialogId: DialogIds.DialogWindow);
                return;
            }

            Loading = true;

            _form.Name = Name;
            var code = Code;
            _form.Remark = Remark;
            var wid = (long)WatchhouseId.Value;
            _form.DeviceGateway = DeviceGateway;
            _form.CountCarEnable = CountCarEnable;
            _form.Direction = Direction;

            _form.Address = Address;
            _form.Latitude = Latitude;
            _form.Longitude = Longitude;
            _form.ManagerPerson = ManagerPerson;
            _form.ManagerPhone = ManagerPhone;
            _form.ManagerCompany = ManagerCompany;
            _form.CompanyPerson = CompanyPerson;
            _form.CompanyPhone = CompanyPhone;


            if (CountCarEnable)
            {
                _form.WarehouseId = (long)WarehouseId.Value;
                _form.WarehouseName = WarehouseId.Label;
            }
            else
            {
                _form.WarehouseId = null;
                _form.WarehouseName = string.Empty;
            }
            var addMode = _form.Id == 0;
            if (addMode)
            {
                _form.Code = code;
                _form.WatchhouseId = wid;
                if (db.Passageways.Any(p => p.Code == code && p.WatchhouseId == wid))
                {
                    FriendlyError("通道编号已存在");
                }
                _form.Id = YitIdHelper.NextId();
                _form.CreateDate = DateTime.Now;
                db.Passageways.Add(_form);
            }
            else
            {
                if ((_form.Code != code || _form.WatchhouseId != wid)
                    && db.Passageways.Any(p => p.Code == code && p.WatchhouseId == wid))
                {
                    FriendlyError("通道编号已存在");
                }
                _form.Code = code;
                _form.WatchhouseId = wid;
                _form.UpdateDate = DateTime.Now;
                db.Entry(_form).State = EntityState.Modified;
            }

            await db.SaveChangesAsync();

            var result = await _appointSvc.API.UploadPssagewayAsync(new PssagewayParams
            {
                Passageway = _form,
                Watchhouse = WatchHouseOptions.FirstOrDefault(p => (long)p.Value == _form.WatchhouseId).OtherData as Watchhouse,
                Operation = !_form.Synchronized ? DataOperationType.新增 : DataOperationType.更新
            });
            if (!result.Success)
            {
                AJCommonDialog.ShowDialog(new AJCommonDialogViewModel.AJCommonDialogParams
                {
                    Title = $"{_appointSvc.API.KeyDescription} 道闸信息同步接口提示",
                    Message = result.Message,
                    Detail = result.Data is Exception ex ? ex.StackTrace : string.Empty
                });
            }
            else
            {
                //必须重新查出来保存, 否则报并发错误
                var dbRecord = db.Passageways.FirstOrDefault(p => p.Id == _form.Id);
                dbRecord.Synchronized = true;
                dbRecord.UpdateDate = DateTime.Now;
                db.Entry(dbRecord).State = EntityState.Modified;
                db.SaveChanges();
            }

            Loading = false;

            if (!result.Success)
            {
                return;
            }

            RequestClose?.Invoke(new DialogResult(ButtonResult.OK));
        }

        bool CanExecuteSaveCmd()
        {
            return !HasErrors;
        }

        private DelegateCommand _resetSyncStatusCmd;
        public DelegateCommand ResetSyncStatusCmd =>
            _resetSyncStatusCmd ?? (_resetSyncStatusCmd = new DelegateCommand(ExecuteResetSyncStatusCmd));

        void ExecuteResetSyncStatusCmd()
        {
            if (MessageBox.Show("请确保台账方不存在此数据,重置后会重新上传至台账", "提示", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
            {
                _form.Synchronized = Synchronized = false;

                MessageBox.Show("请确保数据无误后点击 [保存] 按钮上传至台账", "已重置同步标记", MessageBoxButton.OK);
            }
        }

        public string Title => string.Empty;

        public event Action<IDialogResult> RequestClose;

        public bool CanCloseDialog()
        {
            return true;
        }

        public void OnDialogClosed()
        {

        }

        public async void OnDialogOpened(IDialogParameters parameters)
        {
            parameters.TryGetValue<Passageway>("data", out var data);


            DialogTitle = data == null ? $"新增通道" : $"编辑 {data.Name}";

            var watchhouseSource = await db.Watchhouses.AsNoTracking().OrderBy(p => p.Id).ToListAsync();

            WatchHouseOptions = new ObservableCollection<AJTableFormSchemaItemOptions>(watchhouseSource.Select(p => new AJTableFormSchemaItemOptions
            {
                Label = p.Name,
                Value = p.Id,
                OtherData = p
            }));

            var warehouseList = await db.Warehouses.AsNoTracking()
                .OrderByDescending(p => p.Id).AsNoTracking().ToListAsync();

            WarehouseOptions = new ObservableCollection<AJTableFormSchemaItemOptions>(warehouseList.Select(p => new AJTableFormSchemaItemOptions
            {
                Label = p.Name,
                Value = p.Id,
                OtherData = p
            }));

            PassagewayOptions = await db.Passageways.AsNoTracking().OrderBy(p => p.Id).ToListAsync();

            if (data != null)
            {
                _form = data;

                Name = _form.Name;
                Code = _form.Code;
                Remark = _form.Remark;
                WatchhouseId = WatchHouseOptions.FirstOrDefault(p => (long)p.Value == _form.WatchhouseId);
                DeviceGateway = _form.DeviceGateway;
                CountCarEnable = _form.CountCarEnable;
                Direction = _form.Direction;
                if (_form.WarehouseId.HasValue)
                {
                    WarehouseId = WarehouseOptions
                        .FirstOrDefault(p => (long)p.Value == _form.WarehouseId.GetValueOrDefault());
                }
                Address = _form.Address;
                Latitude = _form.Latitude;
                Longitude = _form.Longitude;
                ManagerPerson = _form.ManagerPerson;
                ManagerPhone = _form.ManagerPhone;
                ManagerCompany = _form.ManagerCompany;
                CompanyPerson = _form.CompanyPerson;
                CompanyPhone = _form.CompanyPhone;
                Synchronized = data.Synchronized;
            }
            else
            {
                WatchhouseId = WatchHouseOptions.FirstOrDefault();
                Direction = PassagewayDirection.进;
                Code = string.Empty;
            }


        }

        private DbService db;
        private AJGlobalExceptionResolvedEvent _globalExceptionEvt;
        private AppointAPISvc _appointSvc;

        public PassagewayFormViewModel(DbService dbIns, AppointAPISvc appointAPISvc, IEventAggregator eventAggregator)
        {
            _form = new Passageway();
            _appointSvc = appointAPISvc;
            _globalExceptionEvt = eventAggregator.GetEvent<AJGlobalExceptionResolvedEvent>();
            _globalExceptionEvt.Subscribe(() =>
            {
                Loading = false;
            });
            db = dbIns;
            DirectionOptions = CommonUtil.EnumToDictionary<PassagewayDirection>(null);
        }
    }
}
